home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / gfx_card / reyes2.lha / REyes / reyes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-13  |  31.0 KB  |  1,226 lines

  1. /*
  2.  * REyes 
  3.  *
  4.  * A screen blanker for the Retina graphics card.
  5.  * By Michael Heinz, 8 January, 1994
  6.  *
  7.  * This software is FREEWARE.  It may be freely distributed for non-commercial use.
  8.  * All rights are reserved by the author.
  9.  *
  10.  * Main routines
  11.  *
  12.  * $Log: reyes.c $
  13.  * Revision 1.4  1994/07/12  16:57:08  mheinz
  14.  * Added copyright notice.
  15.  *
  16.  * Revision 1.3  1994/07/12  16:37:17  mheinz
  17.  * Fixed glitch in filling out NewBroker.
  18.  * Switched Version string to RCS version
  19.  *
  20.  * Revision 1.2  1994/02/07  17:44:57  mheinz
  21.  * Added RCS stuff.
  22.  *
  23.  */
  24.  
  25. #include <exec/memory.h>
  26. #include <exec/ports.h>
  27. #include <exec/execbase.h>
  28. #include <graphics/displayinfo.h>
  29. #include <intuition/intuitionbase.h>
  30. #include <intuition/gadgetclass.h>
  31. #include <libraries/commodities.h>
  32. #include <libraries/gadtools.h>
  33. #include <dos/dosextens.h>
  34. #include <dos/dostags.h>
  35. #include <utility/tagitem.h>
  36.  
  37. #include <clib/alib_protos.h>
  38. #include <clib/commodities_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <clib/exec_protos.h>
  41. #include <clib/gadtools_protos.h>
  42. #include <clib/graphics_protos.h>
  43. #include <clib/intuition_protos.h>
  44. #include <clib/macros.h>
  45. #include <clib/retina_protos.h>
  46. #include <libraries/retina.h>
  47.  
  48. #include <string.h>
  49. #include <stdlib.h>
  50.  
  51. #include <pragmas/commodities_pragmas.h>
  52. #include <pragmas/dos_pragmas.h>
  53. #include <pragmas/exec_pragmas.h>
  54. #include <pragmas/gadtools_pragmas.h>
  55. #include <pragmas/graphics_pragmas.h>
  56. #include <pragmas/intuition_pragmas.h>
  57. #include <pragmas/retina_pragmas.h>
  58.  
  59. #ifdef SMALLEYES
  60. #include "smalleyes.h"
  61. #else
  62. #include "retinaeyes.h"
  63. #endif
  64.  
  65. UBYTE *VersionString = "$VER: $Id: reyes.c 1.4 1994/07/12 16:57:08 mheinz Exp mheinz $";
  66.  
  67. #define NORMAL_WIDE 640
  68. #define NORMAL_HIGH 480
  69. #define SMALL_WIDE 320
  70. #define SMALL_HIGH 240
  71.  
  72. void
  73. chkabort(void)
  74. {
  75. }
  76.  
  77. /*
  78.  * Common Definitions
  79.  */
  80.  
  81. extern struct ExecBase *SysBase;
  82. extern struct DosLibrary *DOSBase;
  83. struct IntuitionBase *IntuitionBase;
  84. struct RetinaBase *RetinaBase;
  85. struct Library *CxBase, *GadToolsBase, *IconBase;
  86.  
  87. #define FINDPROCPORT (&((struct Process *)SysBase->ThisTask)->pr_MsgPort)
  88.  
  89.  
  90. /*
  91.  * A handy request structure for reporting that we've up and died.
  92.  */
  93. struct EasyStruct quitreq =
  94. {
  95.     sizeof(struct EasyStruct),
  96.     0,
  97.     "REyes",
  98.     "REyes has suffered an untimely demise\ndue to: %s",
  99.     "OK|OK"
  100. };
  101.  
  102. void 
  103. Error(char *s)
  104. {
  105.     if (s) EasyRequest(NULL,&quitreq,NULL,s);
  106. }
  107.  
  108. /*
  109.  * Definitions for our Commodity
  110.  */
  111. struct NewBroker NewBroker =
  112. {NB_VERSION, "REyes ", NULL,
  113.  "Somebody's watching you...", NBU_NOTIFY | NBU_UNIQUE, COF_SHOW_HIDE,
  114.  0, NULL, 0};
  115.  
  116. struct MsgPort *CxPort;
  117.  
  118. UBYTE *PopKey;
  119. UBYTE *BlankKey;
  120.  
  121. #define HOTKEY_OPEN_WINDOW 1L
  122. #define HOTKEY_BLANK_SCREEN 2L
  123.  
  124. #define DEF_CX_PRI 0
  125. #define DEF_POPKEY "control alt s"
  126. #define DEF_BLANKKEY "lamiga s"
  127.  
  128. LONG TimeOut, ClientTimeOut;
  129.  
  130. #define MAX_TIMEOUT        3600L
  131. #define MAX_CLIENT_TIMEOUT 60L
  132.  
  133. #define DEF_TIMEOUT        60L
  134. #define DEF_CLIENT_TIMEOUT 5L
  135.  
  136. #define SERVER_PRI 3L
  137. #define CLIENT_PRI -5L
  138.  
  139. /*
  140.  * Definitions for Eye Movement
  141.  */
  142. #define RAND(m) (Random(m)-(m)/2)
  143.  
  144. #define MAX_SPEED     10L
  145. #define MAX_EYES      10L
  146. #define MAX_CHANCE      100L
  147.  
  148. #define DEF_EYES      5L
  149. #define DEF_SPEED     4L
  150. #define DEF_CHANCE      10L
  151.  
  152. #define DEF_MODE MID_DEFAULT_08
  153.  
  154. LONG NumEyes, Speed, Chance;
  155.  
  156. typedef struct {
  157.     int NumEyes;
  158.     Eyes *Eye[MAX_EYES];
  159. } EyeStruct;
  160.  
  161.  
  162. EyeStruct EyeList;
  163.  
  164. /*
  165.  * Definitions for our configuration window
  166.  */
  167.  
  168. struct NewWindow NewBlankerWindow =
  169. {
  170.     80, 16, 0, 0, 0, 1,
  171.     IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_GADGETDOWN |
  172.     IDCMP_GADGETUP | IDCMP_VANILLAKEY | SLIDERIDCMP | LISTVIEWIDCMP,
  173.     WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SIMPLE_REFRESH,
  174.     NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
  175.     WBENCHSCREEN
  176. };
  177.  
  178. struct Window *BlankerWindow;
  179.  
  180. #define GID_HIDE          1
  181. #define GID_BLANK         2
  182. #define GID_QUIT          3
  183. #define GID_TIMEOUT       4
  184. #define GID_CLIENT        5
  185. #define GID_EYES          6
  186. #define GID_SPEED         7
  187. #define GID_CHANCE          8
  188.  
  189. #ifdef SMALLEYES
  190. #define NUM_GADS         7
  191. #else
  192. #define NUM_GADS         8
  193. #endif
  194.  
  195. struct VisualInfo *BlankerVisualInfo;
  196. struct Gadget *BlankerGadgets;
  197. struct TextAttr BlankerAttr =
  198. {"topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT};
  199.  
  200. struct NewGadget NewBlankerGadgets[NUM_GADS] =
  201. {16, 101, 48, 12, "_Hide", &BlankerAttr, GID_HIDE, PLACETEXT_IN, NULL, NULL,
  202.  80, 101, 48, 12, "_Blank", &BlankerAttr, GID_BLANK, PLACETEXT_IN, NULL, NULL,
  203.  144, 101, 48, 12, "_Quit", &BlankerAttr, GID_QUIT, PLACETEXT_IN, NULL, NULL,
  204.  136, 5, 66, 12, "Timeout", &BlankerAttr, GID_TIMEOUT, PLACETEXT_LEFT, NULL, NULL,
  205.  136, 21, 66, 12, "Client Timeout", &BlankerAttr, GID_CLIENT, PLACETEXT_LEFT, NULL, NULL,
  206.  136, 53, 66, 12, "Speed    ", &BlankerAttr, GID_SPEED, PLACETEXT_LEFT, NULL, NULL,
  207.  136, 69, 66, 12, "Eyes     ", &BlankerAttr, GID_EYES, PLACETEXT_LEFT, NULL, NULL,
  208. #ifndef SMALLEYES
  209.  136, 37, 66, 12, "%Anim    ", &BlankerAttr, GID_CHANCE, PLACETEXT_LEFT, NULL, NULL,
  210. #endif
  211. };
  212.  
  213. UBYTE BlankerGadgetKinds[NUM_GADS] =
  214. {
  215.     BUTTON_KIND, BUTTON_KIND, BUTTON_KIND, INTEGER_KIND, INTEGER_KIND, SLIDER_KIND,
  216.     SLIDER_KIND, 
  217. #ifndef SMALLEYES
  218.     SLIDER_KIND
  219. #endif
  220. };
  221.  
  222. struct TagItem ButtonGadgetTags[] =
  223. {GT_Underscore, (ULONG) '_', TAG_DONE, 0L};
  224.  
  225. struct TagItem TimeGadgetTags[] =
  226. {GTIN_Number, 0L, GTIN_MaxChars, 4L, TAG_DONE, 0L};
  227.  
  228. struct TagItem ClientGadgetTags[] =
  229. {GTIN_Number, 0L, GTIN_MaxChars, 2L, TAG_DONE, 0L};
  230.  
  231. struct TagItem ChanceGadgetTags[] =
  232. {GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_CHANCE, GTSL_LevelFormat, 0L,
  233.  GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 3L, GA_RELVERIFY, TRUE,
  234.  TAG_DONE, 0L};
  235.  
  236. struct TagItem SpeedGadgetTags[] =
  237. {GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_SPEED, GTSL_LevelFormat, 0L,
  238.  GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 2L, GA_RELVERIFY, TRUE,
  239.  TAG_DONE, 0L};
  240.  
  241. struct TagItem EyesGadgetTags[] =
  242. {GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_EYES, GTSL_LevelFormat, 0L,
  243.  GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 2L, GA_RELVERIFY, TRUE,
  244.  TAG_DONE, 0L};
  245.  
  246. struct TagItem *BlankerGadgetTagLists[NUM_GADS] =
  247. {
  248.     &ButtonGadgetTags[0],
  249.      &ButtonGadgetTags[0],
  250.      &ButtonGadgetTags[0],
  251.      &TimeGadgetTags[0],
  252.      &ClientGadgetTags[0],
  253.      &SpeedGadgetTags[0],
  254.      &EyesGadgetTags[0],
  255. #ifndef SMALLEYES
  256.      &ChanceGadgetTags[0],
  257. #endif
  258. };
  259.  
  260. /*
  261.  * Definitions for Server/Client Communication
  262.  */
  263.  
  264. BYTE bsp_TimerSig, bsp_InputSig, bsp_ClientSig;
  265. struct Task *ServerProcess;
  266.  
  267. #define MASK(n) (1L<<(n))
  268.  
  269. struct ClientMessage {
  270.     struct Message bcm_Message;
  271.     struct RetinaScreen *bcm_Screen;
  272.     LONG bcm_Status;
  273.     ULONG bcm_SigMask;
  274.     LONG bcm_Eyes, bcm_Speed, bcm_Chance;
  275. };
  276.  
  277. /*
  278.  * The following functions are used to track resources.
  279.  */
  280. struct ToolNode {
  281.     struct ToolNode *Next;
  282.     void *Tool;
  283.     void (*RemProc) (void *, LONG);
  284.     LONG Size;
  285. }
  286.  
  287. *ToolList;
  288.  
  289. void __regargs
  290. RemTool(void *Tool)
  291. {
  292.     struct ToolNode *Ptr, *OPtr;
  293.  
  294.     Ptr = ToolList;
  295.     OPtr = NULL;
  296.     while (Ptr) {
  297.         if (Ptr->Tool==Tool) {
  298.             Ptr->RemProc(Ptr->Tool,Ptr->Size);
  299.             if (OPtr) 
  300.                 OPtr->Next=Ptr->Next;
  301.             else
  302.                 ToolList=Ptr->Next;
  303.             FreeMem(Ptr,sizeof(struct ToolNode));
  304.             return;
  305.         } else {
  306.             OPtr=Ptr;
  307.             Ptr=Ptr->Next;
  308.         }
  309.     }
  310. }
  311.  
  312. void __regargs
  313. Quit(int ReturnCode, char *s)
  314. {
  315.     while (ToolList)
  316.         RemTool(ToolList->Tool);
  317.     if (ReturnCode) Error(s);
  318.     exit(ReturnCode);
  319. }
  320.  
  321. void __regargs
  322. AddTool(void *NewTool, void *ProcPtr, LONG NewSize, char *errmsg)
  323. {
  324.     struct ToolNode *Ptr;
  325.     void (*NewRemProc) (void *, LONG);
  326.  
  327.     NewRemProc = ProcPtr;
  328.     if (NewTool == NULL)
  329.         Quit(10,errmsg);
  330.  
  331.     if ((Ptr = AllocMem(sizeof(struct ToolNode), MEMF_CLEAR)) == NULL) {
  332.         NewRemProc(NewTool, NewSize);
  333.         Quit(20,"Out of Memory.");
  334.     }
  335.     Ptr->Next = ToolList;
  336.     Ptr->Tool = NewTool;
  337.     Ptr->RemProc = NewRemProc;
  338.     Ptr->Size = NewSize;
  339.     ToolList = Ptr;
  340. }
  341.  
  342. /*
  343.  * Some utility functions
  344.  */
  345.  
  346. void __stdargs
  347. DeleteMsgPortSafely(struct MsgPort *AnyPort)
  348. {
  349.     struct Message *AnyMsg;
  350.  
  351.     while (AnyMsg = GetMsg(AnyPort))
  352.         ReplyMsg(AnyMsg);
  353.     DeleteMsgPort(AnyPort);
  354. }
  355.  
  356. int __regargs
  357. ArgIntMax(char **ToolTypes, char *ID, int Default, int Max)
  358. {
  359.     int Val;
  360.  
  361.     Val = ArgInt(ToolTypes, ID, Default);
  362.     if ((Val < 1) || (Val > Max))
  363.         return Default;
  364.     else
  365.         return Val;
  366. }
  367.  
  368. /*
  369.  * The "InputHandler".  It signals the server process
  370.  * when an input or timer event is received.
  371.  */
  372.  
  373. void __interrupt __saveds
  374. BlankerAction(CxMsg * CxMsg, CxObj * CO)
  375. {
  376.     struct InputEvent *IE;
  377.  
  378.     IE = (struct InputEvent *)CxMsgData(CxMsg);
  379.     if (IE->ie_Class == IECLASS_TIMER)
  380.         Signal(ServerProcess, 1L << bsp_TimerSig);
  381.     else
  382.         Signal(ServerProcess, 1L << bsp_InputSig);
  383. }
  384.  
  385. /*
  386.  * Functions for Handling the Configuration Window
  387.  */
  388.  
  389. LONG
  390. GetNum(struct Gadget *Gadget, LONG * Data, LONG Max)
  391. {
  392.     LONG NewData;
  393.  
  394.     NewData = ((struct StringInfo *)Gadget->SpecialInfo)->LongInt;
  395.     if ((NewData < 1L) || (NewData > Max)) {
  396.         GT_SetGadgetAttrs(Gadget, BlankerWindow, NULL, GTIN_Number, (ULONG) * Data, 
  397.                           TAG_DONE);
  398.         return FALSE;
  399.     } else {
  400.         *Data = NewData;
  401.         return TRUE;
  402.     }
  403. }
  404.  
  405. void
  406. CloseBlankerWindow(void)
  407. {
  408.     if (BlankerWindow) {
  409.         /* 
  410.          * We save the current position of the window
  411.          * so it will re-open in the same place, later.
  412.          */
  413.         NewBlankerWindow.LeftEdge = BlankerWindow->LeftEdge;
  414.         NewBlankerWindow.TopEdge = BlankerWindow->TopEdge;
  415.  
  416.         RemTool(BlankerGadgets);
  417.         RemTool(BlankerVisualInfo);
  418.         RemTool(BlankerWindow);
  419.         BlankerWindow = NULL;
  420.     }
  421. }
  422.  
  423. void
  424. OpenBlankerWindow(void)
  425. {
  426.     struct Gadget *Ptr;
  427.     UWORD Index;
  428.     static char Title[80];
  429.  
  430.     if (BlankerWindow == NULL) {
  431.         strcpy(Title, "REyes = <");
  432.         strcat(Title, PopKey);
  433.         strcat(Title, ">");
  434.  
  435.         if (BlankerWindow = OpenWindowTags(&NewBlankerWindow, WA_Title, Title,
  436.                                                WA_AutoAdjust, TRUE, WA_InnerWidth, 
  437.                                             212, WA_InnerHeight, 118, TAG_DONE)) {
  438.                                
  439.             AddTool(BlankerWindow, CloseWindow, NULL,"Could not open the window.");
  440.  
  441.             if ((BlankerVisualInfo = GetVisualInfo(BlankerWindow->WScreen, TAG_DONE)) 
  442.                 == NULL) {
  443.                 RemTool(BlankerWindow);
  444.                 return;
  445.             }
  446.             AddTool(BlankerVisualInfo, FreeVisualInfo, 0L, 
  447.                     "Couldn't get visual data.");
  448.  
  449.             BlankerGadgets = NULL;
  450.             if ((Ptr = CreateContext(&BlankerGadgets)) == NULL) {
  451.                 RemTool(BlankerVisualInfo);
  452.                 RemTool(BlankerWindow);
  453.                 return;
  454.             }
  455.             AddTool(Ptr, FreeGadgets, 0L,"Couldn't allocate the gadgets.");
  456.  
  457.             /* Here we re-load the gadgets with the current settings. */
  458.             TimeGadgetTags[0].ti_Data = (ULONG) TimeOut;
  459.             ClientGadgetTags[0].ti_Data = (ULONG) ClientTimeOut;
  460.             SpeedGadgetTags[0].ti_Data = (ULONG) Speed;
  461.             SpeedGadgetTags[3].ti_Data = (ULONG) "%2ld";
  462. #ifndef SMALLEYES
  463.             ChanceGadgetTags[0].ti_Data = (ULONG) Chance;
  464.             ChanceGadgetTags[3].ti_Data = (ULONG) "%3ld";
  465. #endif
  466.             EyesGadgetTags[0].ti_Data = (ULONG) NumEyes;
  467.             EyesGadgetTags[3].ti_Data = (ULONG) "%2ld";
  468.  
  469.             for (Index = 0L; Index < NUM_GADS; Index++) {
  470.                 NewBlankerGadgets[Index].ng_TopEdge += BlankerWindow->BorderTop;
  471.  
  472.                 NewBlankerGadgets[Index].ng_VisualInfo = BlankerVisualInfo;
  473.                 Ptr = CreateGadgetA((ULONG) BlankerGadgetKinds[Index], Ptr,
  474.                                     &NewBlankerGadgets[Index], 
  475.                                     BlankerGadgetTagLists[Index]);
  476.                 if (Ptr == NULL) {
  477.                     CloseBlankerWindow();
  478.                     return;
  479.                 }
  480.                 NewBlankerGadgets[Index].ng_TopEdge -= BlankerWindow->BorderTop;
  481.             }
  482.  
  483.             AddGList(BlankerWindow, BlankerGadgets, 0L, -1L, NULL);
  484.             RefreshGadgets(BlankerGadgets, BlankerWindow, NULL);
  485.             GT_RefreshWindow(BlankerWindow, NULL);
  486.         }
  487.     }
  488.     ScreenToFront(BlankerWindow->WScreen);
  489.     WindowToFront(BlankerWindow);
  490.     ActivateWindow(BlankerWindow);
  491. }
  492.  
  493. /*
  494.  * Function to handle the Commodity Stuff
  495.  */
  496.  
  497. void __regargs
  498. HandleCxMsg(CxObj * Broker, CxMsg * CxMsg, LONG * TimeUntilBlank,
  499.             LONG * ThisTimeOut)
  500. {
  501.     ULONG MsgType, MsgID;
  502.  
  503.     MsgType = CxMsgType(CxMsg);
  504.     MsgID = CxMsgID(CxMsg);
  505.     ReplyMsg((struct Message *)CxMsg);
  506.  
  507.     switch (MsgType) {
  508.         case CXM_IEVENT:        /* a hotkey was pressed */
  509.             switch (MsgID) {
  510.                 case HOTKEY_OPEN_WINDOW:
  511.                     OpenBlankerWindow();
  512.                     break;
  513.                 case HOTKEY_BLANK_SCREEN:
  514.                     if (*TimeUntilBlank)
  515.                         *TimeUntilBlank = *ThisTimeOut = 2L;
  516.             }
  517.         case CXM_COMMAND:
  518.             switch (MsgID) {
  519.                 case CXCMD_DISABLE:    /* Message from Exchange
  520.                                          * (except CXCMD_UNIQUE) */
  521.                     (void)ActivateCxObj(Broker, FALSE);
  522.                     break;
  523.                 case CXCMD_ENABLE:
  524.                     (void)ActivateCxObj(Broker, TRUE);
  525.                     break;
  526.                 case CXCMD_UNIQUE:
  527.                 case CXCMD_APPEAR:
  528.                     OpenBlankerWindow();
  529.                     break;
  530.                 case CXCMD_DISAPPEAR:
  531.                     CloseBlankerWindow();
  532.                     break;
  533.                 case CXCMD_KILL:
  534.                     Quit(0,"Normal Termination.");
  535.             }
  536.     }
  537. }
  538.  
  539. #ifdef OBSOLETE
  540. /*
  541.  * These functions have been replaced by defines.
  542.  * They're provided here for hysterical raisins.
  543.  */
  544. void
  545. SpritesOff(struct RetinaScreen *rs)
  546. {
  547.     struct TagItem tags[] =
  548.     {RSP_On, 0L, TAG_DONE, 0L};
  549.  
  550.     Retina_SpriteFunction(rs, tags);
  551. }
  552.  
  553. void
  554. SpritesOn(struct RetinaScreen *rs)
  555. {
  556.     struct TagItem tags[] =
  557.     {RSP_On, 1L, TAG_DONE, 0L};
  558.  
  559.     Retina_SpriteFunction(rs, tags);
  560. }
  561. #else
  562. /*
  563.  * We use defines for these functions just to pick up a little speed.
  564.  */
  565.  
  566. #define SpritesOff(rs)                 \
  567. {                                    \
  568.     struct TagItem tags[] =            \
  569.     {RSP_On, 0L, TAG_DONE, 0L};        \
  570.                                     \
  571.     Retina_SpriteFunction(rs, tags);\
  572. }
  573.     
  574. #define SpritesOn(rs)                \
  575. {                                    \
  576.     struct TagItem tags[] =            \
  577.     {RSP_On, 1L, TAG_DONE, 0L};        \
  578.                                     \
  579.     Retina_SpriteFunction(rs, tags);\
  580. }
  581. #endif
  582.  
  583. /*
  584.  * This, annoyingly enough, is neccessary because Retina_CloseScreen is
  585.  * actually a #pragma and not a real function call.  This means you
  586.  * can't pass a pointer to Retina_CloseScreen as a function argument
  587.  * to AddTool.  By adding this wrapper function, we make AddTool work.
  588.  */
  589. void
  590. DestroyScreen(struct RetinaScreen *rs)
  591. {
  592.     Retina_CloseScreen(rs);
  593. }
  594.  
  595. /*
  596.  * Create Screen will first attempt to open a "normal" resolution screen.
  597.  * If that fails, it will try opening a lower resolution screen.
  598.  * If that fails it will return NULL.
  599.  */
  600. struct RetinaScreen *
  601. CreateScreen(void)
  602. {
  603.     struct RetinaScreen *Screen;
  604.  
  605.     if (!(Screen = Retina_OpenScreen(NORMAL_WIDE, NORMAL_HIGH, MID_DEFAULT_08, 
  606.                                      RSFF_DOUBLEBUFFER, NULL))) 
  607.         if (!(Screen = Retina_OpenScreen(SMALL_WIDE, SMALL_HIGH, MID_DEFAULT_08, 
  608.                                          RSFF_DOUBLEBUFFER, NULL))) 
  609.             return NULL;
  610.     
  611.     Retina_LoadPalette(Screen, 0, EYES_COLS, color_table);
  612.     SpritesOff(Screen);
  613.     return Screen;
  614. }
  615.  
  616. /*
  617.  * Functions for Creating/Deleting the Client Process
  618.  */
  619.  
  620. void __stdargs
  621. DeleteBlankerClient(struct MsgPort * ClientPort)
  622. {
  623.     struct ClientMessage ClientMessage;
  624.  
  625.     /* Send the terminating message to the client. 
  626.      * We kick up the client's priority to ensure a 
  627.      * prompt response.
  628.      */
  629.     Forbid();
  630.     ClientMessage.bcm_Message.mn_ReplyPort = FINDPROCPORT;
  631.     PutMsg(ClientPort, (struct Message *)&ClientMessage);
  632.     
  633.     (void)SetTaskPri(ClientPort->mp_SigTask, SERVER_PRI);
  634.     Permit();
  635.     
  636.     /* Get the response. */
  637.     (void)WaitPort(ClientMessage.bcm_Message.mn_ReplyPort);
  638.     (void)GetMsg(ClientMessage.bcm_Message.mn_ReplyPort);
  639. }
  640.  
  641. struct MsgPort *__regargs
  642. CreateBlankerClient(void *ClientRoutine, struct ClientMessage *ClientMessage)
  643. {
  644.     struct Process *ClientProcess;
  645.     struct TagItem ProcTags[3];
  646.  
  647.     ProcTags[0].ti_Tag = NP_Entry;
  648.     ProcTags[0].ti_Data = (ULONG) ClientRoutine;
  649.     ProcTags[1].ti_Tag = NP_Name;
  650.     ProcTags[1].ti_Data = (ULONG) "ClientProcess";
  651.     ProcTags[2].ti_Tag = TAG_DONE;
  652.  
  653.     if (ClientProcess = CreateNewProc(ProcTags)) {
  654.         ClientMessage->bcm_Message.mn_ReplyPort = FINDPROCPORT;
  655.         PutMsg(&ClientProcess->pr_MsgPort, (struct Message *)ClientMessage);
  656.  
  657.         (void)WaitPort(ClientMessage->bcm_Message.mn_ReplyPort);
  658.         (void)GetMsg(ClientMessage->bcm_Message.mn_ReplyPort);
  659.  
  660.         (void)SetTaskPri((struct Task *)ClientProcess, CLIENT_PRI);
  661.  
  662.         if (ClientMessage->bcm_Status)
  663.             return &ClientProcess->pr_MsgPort;
  664.     }
  665.     return NULL;
  666. }
  667.  
  668. /*
  669.  * Functions for Creating/Drawing/Removing the Eyes
  670.  */
  671.  
  672. LONG __inline
  673. Insure1(LONG val)
  674. {
  675.     return ((val == 0) ? 1 : val);    /* return value that is at least 1 */
  676. }
  677.  
  678. /* 
  679.  * This is a fairly high-speed psuedo random number generator,
  680.  * but it's not to random, though.  Occasionally, it will
  681.  * be non-random enough for a while to cause all the Eyes to
  682.  * move in the same direction (or some such.)  I use it
  683.  * because it's fast and because, with all the collision 
  684.  * detection done now, it's less likely the un-randomness
  685.  * will be noticed.
  686.  */
  687. WORD __regargs
  688. Random(WORD Max)
  689. {
  690.     static ULONG Num = 0L;
  691.     ULONG Sec, Mic;
  692.  
  693.     CurrentTime((ULONG *) & Sec, (ULONG *) & Mic);
  694.  
  695.     Num *= Sec;
  696.     Num += Mic;
  697.  
  698.     while (Num > 32767L)
  699.         Num = Num >> 1;
  700.  
  701.     return (WORD)(Num % Max);
  702. }
  703.  
  704. /*
  705.  * Free up the list of eyes.
  706.  */
  707. void __regargs
  708. DeleteEyes(EyeStruct *EyeList)
  709. {
  710.     LONG i;
  711.  
  712.     for (i=0;i<EyeList->NumEyes;i++) 
  713.         if (EyeList->Eye[i]!=NULL) FreeMem(EyeList->Eye[i],sizeof(Eyes));
  714. }
  715.  
  716. /*
  717.  * Create the list of eyes.
  718.  */
  719. EyeStruct *__regargs
  720. CreateEyes(struct RetinaScreen *Screen,
  721.             LONG NumEyes, LONG Speed)
  722. {
  723.     int Index, i, flag, count;
  724.     Eyes *randomeyes[4];
  725.     
  726.     if (!Screen) return NULL;
  727.     
  728.     randomeyes[0]=&BlueEyes;
  729.     randomeyes[1]=&GreenEyes;
  730.     randomeyes[2]=&VioletEyes;
  731.     randomeyes[3]=&BrownEyes;
  732.  
  733.     /*
  734.      * Create the Eyes
  735.      */
  736.     for (Index = 0; Index < NumEyes; Index++) {
  737.         if (!(EyeList.Eye[Index]=AllocMem(sizeof(Eyes),MEMF_PUBLIC|MEMF_CLEAR))) 
  738.             Quit(20,"Out of Memory!!!");
  739.         CopyMem(randomeyes[Random(4)],EyeList.Eye[Index],sizeof(Eyes));
  740. #ifndef SMALLEYES
  741.         EyeList.Eye[Index]->currentframe=Random(EyeList.Eye[Index]->maxframes);
  742. #else
  743.         EyeList.Eye[Index]->currentframe=0;
  744. #endif
  745.            EyeList.Eye[Index]->xspeed=Insure1(RAND(Speed));
  746.            EyeList.Eye[Index]->yspeed=Insure1(RAND(Speed));
  747.         count=0; flag=1;
  748.  
  749.         /* 
  750.          * We try 4 times to fit an eye pair on the screen.  If we can't, then
  751.          * the screen must be too small for the # of eyes and we truncate the list.
  752.          */
  753.         while (flag & count<4) {
  754.             EyeList.Eye[Index]->xpos=Random(Screen->rs_Width-
  755.                                             EyeList.Eye[Index]->width);
  756.             EyeList.Eye[Index]->ypos=Random(Screen->rs_Height-
  757.                                             EyeList.Eye[Index]->height);
  758.             flag=0;
  759.             for (i=0;i<Index; i++) {
  760.                 /* Looking for overlapping rectangles... */
  761.                 if ((EyeList.Eye[i]->xpos>
  762.                      EyeList.Eye[Index]->xpos-EyeList.Eye[i]->width)&&
  763.                     (EyeList.Eye[i]->xpos<
  764.                      EyeList.Eye[Index]->xpos+EyeList.Eye[Index]->width)&&
  765.                     (EyeList.Eye[i]->ypos>
  766.                      EyeList.Eye[Index]->ypos-EyeList.Eye[i]->height)&&
  767.                     (EyeList.Eye[i]->ypos<
  768.                      EyeList.Eye[Index]->ypos+EyeList.Eye[Index]->height)) {
  769.                     flag=1;
  770.                     break;
  771.                 }
  772.             }
  773.         }
  774.         if (flag) {    /* If we failed to add an Eye pair, truncate the list. */
  775.             NumEyes=Index+1;
  776.             break;
  777.         }
  778.     }
  779.  
  780.     EyeList.NumEyes=NumEyes;
  781.     
  782.     return &EyeList;
  783. }
  784.  
  785. /* move the Eyes and redraw them */
  786.  
  787. void __regargs
  788. DrawEyes(EyeStruct *EyeList, struct RetinaScreen *rs, LONG Chance)
  789. {
  790.     int Index,i;
  791.     Eyes **EL;
  792.  
  793.     /* 
  794.      * This assignment provides a (very mild) speed up buy removing
  795.      * one level of indirection from all the work that's going on below.
  796.      */
  797.     EL=EyeList->Eye;
  798.  
  799.     Chance=Insure1(100-Chance);
  800.  
  801.     /* If we don't have a screen, don't draw on it! (duh.) */
  802.     if (!rs) return; 
  803.  
  804.     for (Index=0; Index<EyeList->NumEyes; Index++) {
  805.         /* Move the Eye. */
  806.         EL[Index]->old_xpos=EL[Index]->xpos;
  807.         EL[Index]->old_ypos=EL[Index]->ypos;
  808.         EL[Index]->xpos+=EL[Index]->xspeed;
  809.         EL[Index]->ypos+=EL[Index]->yspeed;
  810.         
  811.         /* Bounce check */
  812.         if (EL[Index]->xpos<0) { 
  813.             EL[Index]->xpos=0; 
  814.             EL[Index]->xspeed=Insure1(RAND(Speed));
  815.         } else if (EL[Index]->xpos>rs->rs_Width-EL[Index]->width-1) {
  816.             EL[Index]->xpos=rs->rs_Width-EL[Index]->width-1;
  817.             EL[Index]->xspeed=Insure1(RAND(Speed));
  818.         }
  819.         if (EL[Index]->ypos<0) { 
  820.             EL[Index]->ypos=0; 
  821.             EL[Index]->yspeed=Insure1(RAND(Speed));
  822.         } else if (EL[Index]->ypos>rs->rs_Height-EL[Index]->height-1) {
  823.             EL[Index]->ypos=rs->rs_Height-EL[Index]->height-1;
  824.             EL[Index]->yspeed=Insure1(RAND(Speed));
  825.         }
  826.  
  827.         /* 
  828.          * Collision check... 
  829.          * If we detect that we hit one other eye pair, we reverse direction.
  830.          * Note - checking stops after the first collision, otherwise
  831.          * multiple-collisions might cause the eye pair to continue in
  832.          * the same direction (i.e., its direction got negated twice)
  833.          */
  834.         for (i=0;i<EyeList->NumEyes; i++) {
  835.             if (i!=Index) {
  836.                 if ((EL[i]->xpos>EL[Index]->xpos-EL[i]->width)&&
  837.                     (EL[i]->xpos<EL[Index]->xpos+EL[Index]->width)&&
  838.                     (EL[i]->ypos>EL[Index]->ypos-EL[i]->height)&&
  839.                     (EL[i]->ypos<EL[Index]->ypos+EL[Index]->height)) {
  840.  
  841.                     EL[Index]->yspeed= (EL[Index]->yspeed>0)?-Insure1(Random(Speed/2)):Insure1(Random(Speed/2));
  842.                     EL[Index]->xspeed= (EL[Index]->xspeed>0)?-Insure1(Random(Speed/2)):Insure1(Random(Speed/2));
  843.                     EL[Index]->xpos=EL[Index]->old_xpos;
  844.                     EL[Index]->ypos=EL[Index]->old_ypos;
  845.                     break;
  846.                 }
  847.             }
  848.         }
  849. #ifndef SMALLEYES
  850.         /* Are we animating this Eye pair? */
  851.         if (EL[Index]->currentframe) {
  852.             if (!EL[Index]->tic) {
  853.                 EL[Index]->tic++;
  854.             } else {
  855.                 EL[Index]->tic=0;
  856.                 EL[Index]->currentframe=(EL[Index]->currentframe+1)%
  857.                                     EL[Index]->maxframes;
  858.             }
  859.         /* No?  Then roll the dice and see if we should start... */
  860.         } else if (!Random(Chance)) { 
  861.             EL[Index]->currentframe=1;
  862.         }
  863. #endif
  864.             
  865.     }
  866.  
  867.     /* Redraw on the background bitmap... */
  868.     for (Index=0; Index<EyeList->NumEyes; Index++) {
  869.         Retina_WriteRect(EL[Index]->animtable[EL[Index]->currentframe],
  870.                          0,0,
  871.                          EL[Index]->width, RECTMODE_256,
  872.                          rs,EL[Index]->xpos, EL[Index]->ypos,
  873.                          EL[Index]->width, EL[Index]->height, NULL);   
  874.         
  875.     }
  876.         
  877.     /* Swap the bitmaps */
  878.     Retina_SwapBitMap(rs);
  879.  
  880.     /* Erase the old images on the new background bitmap. */
  881.     for (Index=0; Index<EyeList->NumEyes; Index++) {
  882.         Retina_RectFill(rs,EL[Index]->old_xpos,
  883.                         EL[Index]->old_ypos,
  884.                         EL[Index]->old_xpos+EL[Index]->width,
  885.                         EL[Index]->old_ypos+EL[Index]->height);
  886.     }
  887. }
  888.  
  889. /*
  890.  * This is the Client Process's Main Loop
  891.  */
  892.  
  893. void __interrupt __saveds
  894. REyesClientProcess(void)
  895. {
  896.     struct ClientMessage *ClientMessage;
  897.     struct MsgPort *ClientPort;
  898.     struct Task *ServerTask;
  899.     ULONG ServerSigMask;
  900.     struct RetinaScreen *EyesScreen;
  901.     LONG NumEyes, Speed, Chance;
  902.     EyeStruct *EyeList;
  903.  
  904.     /* wait for Server's initial Message */
  905.  
  906.     ClientPort = FINDPROCPORT;
  907.     (void)WaitPort(ClientPort);
  908.     ClientMessage = (struct ClientMessage *)GetMsg(ClientPort);
  909.  
  910.     ServerTask = ClientMessage->bcm_Message.mn_ReplyPort->mp_SigTask;
  911.     ServerSigMask = ClientMessage->bcm_SigMask;
  912.  
  913.     NumEyes = ClientMessage->bcm_Eyes;
  914.     Speed = ClientMessage->bcm_Speed;
  915.     Chance = ClientMessage->bcm_Chance;
  916.     EyesScreen = ClientMessage->bcm_Screen;
  917.  
  918.     if (EyesScreen) {
  919.         if ((EyeList = CreateEyes(EyesScreen, NumEyes, Speed))== NULL) {
  920.             ClientMessage->bcm_Status = FALSE;
  921.             Forbid();
  922.             ReplyMsg((struct Message *)ClientMessage);
  923.             return;
  924.         }
  925.     }
  926.             
  927.     ClientMessage->bcm_Status = TRUE;
  928.     ReplyMsg((struct Message *)ClientMessage);
  929.  
  930.     /* Animate the blanker screen until a termination message is received. */
  931.     while ((ClientMessage = (struct ClientMessage *)GetMsg(ClientPort)) == NULL) {
  932.         if (EyesScreen) DrawEyes(EyeList, EyesScreen, Chance);
  933.     
  934.         /* 
  935.          * We signal the server after each loop so it will know that we're alive.
  936.          */
  937.         Signal(ServerTask, ServerSigMask);
  938.     }
  939.  
  940.     /* We are requested to finish, so we do. */
  941.  
  942.     if (EyeList) DeleteEyes(EyeList);
  943.     Forbid();
  944.     ReplyMsg((struct Message *)ClientMessage);
  945. }
  946.  
  947. /*
  948.  * The Main Loop
  949.  */
  950.  
  951. void
  952. main(LONG argc, UBYTE * argv[])
  953. {
  954.     char **ToolTypes;
  955.     CxObj *Broker, *ObjectList, *Filter;
  956.     struct IntuiMessage *IntMsg;
  957.     CxMsg *BlankerCxMsg;
  958.     LONG ThisTimeOut, TimeUntilBlank, TimeUntilBlack;
  959.     struct RetinaScreen *BlankerScreen = NULL;
  960.     struct MsgPort *ClientPort = NULL;
  961.     int BlankFlag=0;
  962.  
  963.     /* open our Libraries */
  964.     AddTool(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",
  965.                                               37L), CloseLibrary, 0L,
  966.             "Couldn't open the intuition.library.");
  967.     AddTool(IconBase = OpenLibrary("icon.library", 37L), CloseLibrary, 0L,
  968.             "Couldn't open the icon library.");
  969.     AddTool(CxBase = OpenLibrary("commodities.library", 37L), CloseLibrary, 0L,
  970.             "Couldn't open the commoidities library.");
  971.     AddTool(GadToolsBase = OpenLibrary("gadtools.library", 37L), CloseLibrary, 0L,
  972.             "Couldn't open the gadtools library.");
  973.     AddTool(RetinaBase = (struct _xy_RetinaBase *)OpenLibrary("retina.library", 7L), 
  974.             CloseLibrary, 0L,"Couldn't open the Retina library.");
  975.  
  976.     /* get our Arguments */
  977.  
  978.     if (ToolTypes = ArgArrayInit(argc, argv))
  979.         AddTool(ToolTypes, ArgArrayDone, 0L,NULL);
  980.  
  981.     /* get some Signals */
  982.  
  983.     ServerProcess = SysBase->ThisTask;
  984.     if ((bsp_TimerSig = AllocSignal(-1L)) == -1)
  985.         Quit(10,"Could not allocate a signal.");
  986.     AddTool((void *)bsp_TimerSig, FreeSignal, 0L,NULL);
  987.     if ((bsp_InputSig = AllocSignal(-1L)) == -1)
  988.         Quit(10,"Could not allocate a signal.");
  989.     AddTool((void *)bsp_InputSig, FreeSignal, 0L,NULL);
  990.     if ((bsp_ClientSig = AllocSignal(-1L)) == -1)
  991.         Quit(10,"Could not allocate a signal.");
  992.     AddTool((void *)bsp_ClientSig, FreeSignal, 0L,NULL);
  993.  
  994.     /* initialize our Broker = install us as a Commodity */
  995.  
  996.     AddTool(CxPort = CreateMsgPort(), DeleteMsgPortSafely, 0L, 
  997.             "Failed to create a port.");
  998.  
  999.     VersionString[36]='\0'; /* This string is filled out by RCS.  We need to shorten it. */
  1000.     NewBroker.nb_Title=&VersionString[11];
  1001.     NewBroker.nb_Pri = ArgInt(ToolTypes, "CX_PRIORITY", DEF_CX_PRI);
  1002.     NewBroker.nb_Port = CxPort;
  1003.     AddTool(Broker = CxBroker(&NewBroker, NULL), DeleteCxObjAll, 0L, 
  1004.             NULL);
  1005.  
  1006.     /* get Time Out, Client Time Out and Display mode */
  1007.  
  1008.     TimeOut = ArgIntMax(ToolTypes, "TIMEOUT", DEF_TIMEOUT, MAX_TIMEOUT);
  1009.     ClientTimeOut = ArgIntMax(ToolTypes, "CLIENTTIMEOUT", DEF_CLIENT_TIMEOUT, 
  1010.                                 MAX_CLIENT_TIMEOUT);
  1011.  
  1012.     /* get Parameters for Eye Movement */
  1013.  
  1014.     NumEyes = ArgIntMax(ToolTypes, "EYES", DEF_EYES, MAX_EYES);
  1015.     Speed = ArgIntMax(ToolTypes, "SPEED", DEF_SPEED, MAX_SPEED);
  1016.     Chance = ArgIntMax(ToolTypes, "%ANIM", DEF_CHANCE, MAX_CHANCE);
  1017.  
  1018.     /* install our hot keys */
  1019.  
  1020.     PopKey = ArgString(ToolTypes, "CX_POPKEY", DEF_POPKEY);
  1021.     BlankKey = ArgString(ToolTypes, "BLANKKEY", DEF_BLANKKEY);
  1022.  
  1023.     if ((Filter = HotKey(PopKey, CxPort, HOTKEY_OPEN_WINDOW)) == NULL)
  1024.         Quit(10,"The CX_POPKEY tool type is invalid.");
  1025.     else
  1026.         AttachCxObj(Broker, Filter);
  1027.     if (CxObjError(Filter))
  1028.         Quit(10,"Could not link to the commodity list.");
  1029.  
  1030.     if ((Filter = HotKey(BlankKey, CxPort, HOTKEY_BLANK_SCREEN)) == NULL)
  1031.         Quit(10,"The BLANKKEY tool type is invalid.");
  1032.     else
  1033.         AttachCxObj(Broker, Filter);
  1034.     if (CxObjError(Filter))
  1035.         Quit(10,"Could not link to the commodity list.");
  1036.  
  1037.     /* install our "InputHandler" */
  1038.  
  1039.     ObjectList = CxCustom(BlankerAction, 0L);
  1040.     AttachCxObj(Broker, ObjectList);
  1041.     if (CxObjError(ObjectList))
  1042.         Quit(10,"Could not link to the commodity list.");
  1043.  
  1044.     (void)ActivateCxObj(Broker, TRUE);
  1045.     AddTool(Broker, ActivateCxObj, 0L,"The broker broke.");
  1046.  
  1047.     /* open Window on startup if not forbidden */
  1048.  
  1049.     if (stricmp(ArgString(ToolTypes, "CX_POPUP", ""), "NO"))
  1050.         OpenBlankerWindow();
  1051.  
  1052.     /* 
  1053.      * increase our Priority 
  1054.      * Note that when we quit, our priority will be reset to what it
  1055.      * was before.
  1056.      */
  1057.  
  1058.     AddTool(FindTask(NULL), SetTaskPri, (LONG) SetTaskPri(FindTask(NULL), SERVER_PRI),
  1059.             "Findtask failed!");
  1060.  
  1061.     /* start the Loop */
  1062.  
  1063.     TimeUntilBlank = ThisTimeOut = 10L * TimeOut;
  1064.     TimeUntilBlack = 10L * ClientTimeOut;
  1065.  
  1066.     FOREVER
  1067.     {
  1068.         ULONG Mask;
  1069.  
  1070.         if (BlankerWindow)
  1071.             Mask = Wait(MASK(bsp_TimerSig) | MASK(bsp_InputSig) | MASK(bsp_ClientSig) |
  1072.                         MASK(CxPort->mp_SigBit) | 
  1073.                         MASK(BlankerWindow->UserPort->mp_SigBit) |
  1074.                         SIGBREAKF_CTRL_C);
  1075.         else
  1076.             Mask = Wait(MASK(bsp_TimerSig) | MASK(bsp_InputSig) | MASK(bsp_ClientSig) |
  1077.                         MASK(CxPort->mp_SigBit) | SIGBREAKF_CTRL_C);
  1078.  
  1079.         /* process Window Events */
  1080.  
  1081.         while ((BlankerWindow != NULL) && (IntMsg = 
  1082.             GT_GetIMsg(BlankerWindow->UserPort)))
  1083.             switch (IntMsg->Class) {
  1084.                     struct Gadget *Clicked;
  1085.                     UWORD Code;
  1086.  
  1087.                 case IDCMP_CLOSEWINDOW:
  1088.                     GT_ReplyIMsg(IntMsg);
  1089.                     CloseBlankerWindow();
  1090.                     break;
  1091.                 case IDCMP_REFRESHWINDOW:
  1092.                     GT_BeginRefresh(BlankerWindow);
  1093.                     GT_EndRefresh(BlankerWindow, TRUE);
  1094.                     break;
  1095.                 case IDCMP_GADGETUP:
  1096.                     Code = IntMsg->Code;
  1097.                     Clicked = (struct Gadget *)IntMsg->IAddress;
  1098.                     GT_ReplyIMsg(IntMsg);
  1099.                     switch (Clicked->GadgetID) {
  1100.                         case GID_HIDE:
  1101.                             CloseBlankerWindow();
  1102.                             break;
  1103.                         case GID_QUIT:
  1104.                             Quit(0,"Normal Termination.");
  1105.                         case GID_BLANK:
  1106.                             TimeUntilBlank = ThisTimeOut = 2L;
  1107.                             break;
  1108.                         case GID_TIMEOUT:
  1109.                             if (GetNum(Clicked, &TimeOut, MAX_TIMEOUT))
  1110.                                 TimeUntilBlank = ThisTimeOut = 10L * TimeOut;
  1111.                             break;
  1112.                         case GID_CLIENT:
  1113.                             if (GetNum(Clicked, &ClientTimeOut, MAX_CLIENT_TIMEOUT))
  1114.                                 TimeUntilBlack = 10L * ClientTimeOut;
  1115.                             break;
  1116.                         case GID_EYES:
  1117.                             NumEyes = Code;
  1118.                             break;
  1119.                         case GID_SPEED:
  1120.                             Speed = Code;
  1121.                             break;
  1122.                         case GID_CHANCE:
  1123.                             Chance = Code;
  1124.                             break;
  1125.                     }
  1126.                     break;
  1127.                 case IDCMP_VANILLAKEY:
  1128.                     Code = IntMsg->Code;
  1129.                     GT_ReplyIMsg(IntMsg);
  1130.                     switch ((char)Code) {
  1131.                         case 'H':
  1132.                         case 'h':
  1133.                             CloseBlankerWindow();
  1134.                             break;
  1135.                         case 'Q':
  1136.                         case 'q':
  1137.                             Quit(0,"Normal Termination.");
  1138.                         case 'B':
  1139.                         case 'b':
  1140.                             TimeUntilBlank = ThisTimeOut = 2L;
  1141.                     }
  1142.                     break;
  1143.                 default:
  1144.                     GT_ReplyIMsg(IntMsg);
  1145.             }
  1146.  
  1147.         /* process Commodity Messages */
  1148.  
  1149.         while (BlankerCxMsg = (CxMsg *) GetMsg(CxPort))
  1150.             HandleCxMsg(Broker, BlankerCxMsg, &TimeUntilBlank, &ThisTimeOut);
  1151.  
  1152.         /* check for <CTRL>-C */
  1153.  
  1154.         if (Mask & SIGBREAKF_CTRL_C)
  1155.             Quit(0,"Normal Termination.");
  1156.  
  1157.         /* Input detected, unblank if necessary */
  1158.  
  1159.         if (Mask & MASK(bsp_InputSig)) {
  1160.             if (BlankFlag) {
  1161.                 if (ClientPort)
  1162.                     RemTool(ClientPort);
  1163.                 
  1164.                 if (BlankerScreen) {
  1165.                     SpritesOn(BlankerScreen);
  1166.                     RemTool(BlankerScreen);
  1167.                 } else
  1168.                     Retina_DisplayOn();
  1169.                 BlankFlag=0;
  1170.                 ThisTimeOut = 10L * TimeOut;
  1171.             }
  1172.             TimeUntilBlank = ThisTimeOut;
  1173.         }
  1174.  
  1175.         /* client has confirmed that it is still alive */
  1176.         if (Mask & MASK(bsp_ClientSig)) {
  1177.             if (BlankerScreen) Retina_DisplayOn();
  1178.             TimeUntilBlack = 10L * ClientTimeOut;
  1179.             BlankFlag=1;
  1180.         }
  1181.         /* 1/10 sec is over */
  1182.  
  1183.         if (Mask & MASK(bsp_TimerSig))
  1184.             if (TimeUntilBlank) {
  1185.                 TimeUntilBlank--;
  1186.                 if (TimeUntilBlank == 0L) {    /* Time Out reached, blank
  1187.                                              * the screen */
  1188.                     struct ClientMessage ClientMessage;
  1189.  
  1190.                     BlankFlag=1;
  1191.                     BlankerScreen=CreateScreen();
  1192.                     if (BlankerScreen) 
  1193.                         AddTool(BlankerScreen, DestroyScreen, 0L,NULL);
  1194.                     else
  1195.                         /* do this if we're completely out of video memory. */
  1196.                         Retina_DisplayOff();  
  1197.  
  1198.                     ClientMessage.bcm_Screen = BlankerScreen;
  1199.                     ClientMessage.bcm_SigMask = 1L << bsp_ClientSig;
  1200.                     ClientMessage.bcm_Eyes = NumEyes;
  1201.                     ClientMessage.bcm_Speed = Speed;
  1202.                     ClientMessage.bcm_Chance = Chance;
  1203.  
  1204.                     if (ClientPort = CreateBlankerClient(REyesClientProcess, 
  1205.                         &ClientMessage)) {
  1206.                         TimeUntilBlack = 10L * ClientTimeOut;    
  1207.                         /* try to start Client */
  1208.                         AddTool(ClientPort, DeleteBlankerClient, 0L,NULL);
  1209.                     }
  1210.                 }
  1211.             } else {
  1212.                 if ((BlankerScreen)&&(RetinaBase->rb_FirstScreen != BlankerScreen)) {
  1213.                     Retina_ScreenToFront(BlankerScreen);
  1214.                     SpritesOff(BlankerScreen);
  1215.                 }
  1216.                 if (TimeUntilBlack) {
  1217.                     TimeUntilBlack--;
  1218.                     if (TimeUntilBlack == 0L)
  1219.                         Retina_DisplayOff();    /* Client Time Out
  1220.                                                  * reached, turn entire
  1221.                                                  * screen black */
  1222.                 }
  1223.             }
  1224.     }
  1225. }
  1226.